home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
src
/
haeberli
/
libgutil
/
bitmap.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
11KB
|
621 lines
/*
* Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
* All Rights Reserved.
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
* the contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of Silicon Graphics, Inc.
*
* RESTRICTED RIGHTS LEGEND:
* Use, duplication or disclosure by the Government is subject to restrictions
* as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
* and Computer Software clause at DFARS 252.227-7013, and/or in similar or
* successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
* rights reserved under the Copyright Laws of the United States.
*/
/*
* bitmap -
* Support for the allocation, manipulation, and display
* of bitmaps.
*
* Paul Haeberli - 1985
*
*
* exports
*
Bitmap *bmnew(xsize,ysize)
void bmfree(b)
Bitmap *bmclone(b)
void bmop(b,op)
void bmclear(b)
void bmset(b)
void bmxor(b)
void bmrand(b)
void bmpixop(b,x,y,op)
void bmclrpix(b,x,y)
void bmsetpix(b,x,y)
void bmxorpix(b,x,y)
void bmbmop(dst,x,y,src,op)
void bmzap(b)
Bitmap *bmmagnify(b,xmag,ymag)
Bitmap *bmminimize(b)
int bmgetpix(b,x,y)
int bmdomain(b,xmin,ymin,xmax,ymax)
int bmrasbytes(b)
Bitmap *bmread(fname)
Bitmap *bmfromfile(inf)
void bmwrite(fname,b)
void bmtofile(outf,b)
void putbm(port,b)
Bitmap *getbm(val)
void bmdrawbig(b,mag)
void bmbigpix(b,x,y,mag)
void bmprint(bm)
*
*/
#include "gl.h"
#include "device.h"
#include "stdio.h"
#include "port.h"
#include "bitmap.h"
#include "obj.h"
#include "rct.h"
FILE *gfxopen();
#define BMMAGIC 0x5421
static leftmost();
static rightmost();
static int bittab[16] = {
0x8000, 0x4000, 0x2000, 0x1000,
0x0800, 0x0400, 0x0200, 0x0100,
0x0080, 0x0040, 0x0020, 0x0010,
0x0008, 0x0004, 0x0002, 0x0001,
};
Bitmap *bmnew(xsize,ysize)
int xsize, ysize;
{
Bitmap *b;
b = (Bitmap *)mymalloc(sizeof(Bitmap));
b->xsize = xsize;
b->ysize = ysize;
b->xorig = 0;
b->yorig = 0;
b->xmove = 0;
b->ymove = 0;
if(b->ysize>0 && b->ysize>0) {
b->sper = 1+((b->xsize-1)>>4);
b->base = (short *)mymalloc(bmrasbytes(b));
bzero(b->base,bmrasbytes(b));
} else {
b->sper = 0;
b->xsize = 0;
}
return b;
}
void bmfree(b)
Bitmap *b;
{
if(b->base)
free(b->base);
free(b);
}
Bitmap *bmclone(b)
Bitmap *b;
{
Bitmap *c;
c = bmnew(b->xsize,b->ysize);
c->xmove = b->xmove;
c->ymove = b->ymove;
c->xorig = b->xorig;
c->yorig = b->yorig;
if(b->base)
bcopy(b->base,c->base,bmrasbytes(b));
return c;
}
void bmop(b,op)
Bitmap *b;
int op;
{
short *sptr;
int n;
n = b->sper * b->ysize;
sptr = b->base;
switch(op) {
case BM_CLR:
while(n--)
*sptr++ = 0;
break;
case BM_SET:
while(n--)
*sptr++ = 0xffff;
break;
case BM_XOR:
while(n--)
*sptr++ ^= 0xffff;
break;
}
}
void bmclear(b)
Bitmap *b;
{
bmop(b,BM_CLR);
}
void bmset(b)
Bitmap *b;
{
bmop(b,BM_SET);
}
void bmxor(b)
Bitmap *b;
{
bmop(b,BM_XOR);
}
void bmrand(b)
Bitmap *b;
{
char *cptr;
short *sptr;
int n, i;
n = bmrasbytes(b);
cptr = (char *)b->base;
i = 0;
while(n--)
*cptr++ = rand();
}
void bmpixop(b,x,y,op)
Bitmap *b;
unsigned int x, y;
int op;
{
int offset;
if( (x>=b->xsize) || (y>=b->ysize) ) {
fprintf(stderr,"bmpixop: range error\n");
return;
}
offset = y*b->sper + (x >> 4);
switch(op) {
case BM_CLR:
b->base[offset] &= ~bittab[x&0xf];
break;
case BM_SET:
b->base[offset] |= bittab[x&0xf];
break;
case BM_XOR:
b->base[offset] ^= bittab[x&0xf];
break;
}
}
void bmclrpix(b,x,y)
Bitmap *b;
unsigned int x, y;
{
bmpixop(b,x,y,BM_CLR);
}
void bmsetpix(b,x,y)
Bitmap *b;
unsigned int x, y;
{
bmpixop(b,x,y,BM_SET);
}
void bmxorpix(b,x,y)
Bitmap *b;
unsigned int x, y;
{
bmpixop(b,x,y,BM_XOR);
}
void bmbmop(dst,x,y,src,op)
Bitmap *dst, *src;
unsigned int x, y;
int op;
{
int xmax, doff;
int srcymin, srcymax;
int xsrc, ysrc, ydst;
unsigned short *sptr;
unsigned short *dptr;
rct srct, drct, irct;
srct.xmin = 0;
srct.ymin = 0;
srct.xmax = 0+src->xsize;
srct.ymax = 0+src->ysize;
drct.xmin = -x;
drct.ymin = -y;
drct.xmax = dst->xsize-x;
drct.ymax = dst->ysize-y;
if(!rctinter(&srct,&drct,&irct))
return;
srcymin = irct.ymin;
srcymax = irct.ymax;
xmax = src->xsize;
for(ysrc=srcymin; ysrc<srcymax; ysrc++) {
ydst = ysrc+y;
sptr = (unsigned short *)(src->base+(ysrc*src->sper));
dptr = (unsigned short *)(dst->base+((ydst*dst->sper)+(x>>4)));
doff = x&0xf;
if(doff == 0) {
switch(op) {
case BM_CLR:
for(xsrc=0; xsrc<xmax; xsrc+=16)
*dptr++ &= ~(*sptr++);
break;
case BM_SET:
for(xsrc=0; xsrc<xmax; xsrc+=16)
*dptr++ |= *sptr++;
break;
case BM_XOR:
for(xsrc=0; xsrc<xmax; xsrc+=16)
*dptr++ ^= *sptr++;
break;
}
} else {
for(xsrc=0; xsrc<xmax; xsrc+=16) {
switch(op) {
case BM_CLR:
*dptr &= ~(*sptr>>doff);
dptr++;
*dptr &= ~(*sptr<<(16-doff));
sptr++;
break;
case BM_SET:
*dptr |= *sptr>>doff;
dptr++;
*dptr |= *sptr<<(16-doff);
sptr++;
break;
case BM_XOR:
*dptr ^= *sptr>>doff;
dptr++;
*dptr ^= *sptr<<(16-doff);
sptr++;
break;
}
}
}
}
}
void bmzap(b)
Bitmap *b;
{
b->xmove = 0;
b->ymove = 0;
b->xorig = 0;
b->yorig = 0;
}
Bitmap *bmmagnify(b,xmag,ymag)
Bitmap *b;
int xmag, ymag;
{
Bitmap *c;
short *sptr;
int word;
int x, y;
int m;
int xpos, rowstart;
int offset;
c = bmnew(xmag*b->xsize,ymag*b->ysize);
c->xmove = xmag*b->xmove;
c->ymove = ymag*b->ymove;
c->xorig = xmag*b->xorig;
c->yorig = ymag*b->yorig;
sptr = c->base;
rowstart = ymag*y*c->sper;
for(y=0; y<b->ysize; y++) {
xpos = 0;
for(x=0; x<b->xsize; x++) {
if(bmgetpix(b,x,y)) {
for(m=0; m<xmag; m++) {
offset = rowstart + ((xpos) >> 4);
word = sptr[offset];
word |= bittab[xpos&0xf];
sptr[offset] = word;
xpos++;
}
} else
xpos += xmag;
}
for(m=0; m<(ymag-1); m++) {
bcopy(sptr+rowstart,sptr+rowstart+c->sper,c->sper<<1);
rowstart += c->sper;
}
rowstart += c->sper;
}
return c;
}
Bitmap *bmminimize(b)
Bitmap *b;
{
Bitmap *c;
int x, y;
int xsize, ysize;
int xmin, ymin, xmax, ymax;
if(bmdomain(b,&xmin,&ymin,&xmax,&ymax)) {
xsize = xmax-xmin+1;
ysize = ymax-ymin+1;
c = bmnew(xsize,ysize);
for(y=0; y<ysize; y++)
for(x=0; x<xsize; x++) {
if(bmgetpix(b,x+xmin,y+ymin))
bmsetpix(c,x,y);
}
c->xorig = b->xorig-xmin;
c->yorig = b->yorig-ymin;
} else {
c = bmnew(1,1);
}
c->xmove = b->xmove;
c->ymove = b->ymove;
return c;
}
int bmgetpix(b,x,y)
Bitmap *b;
unsigned int x, y;
{
int offset;
if( (x>=b->xsize) || (y>=b->ysize) ) {
fprintf(stderr,"bmgetpix: range error\n");
return 0;
}
offset = y*b->sper + (x >> 4);
if(b->base[offset] & bittab[x&0xf])
return 1;
else
return 0;
}
int bmdomain(b,xmin,ymin,xmax,ymax)
Bitmap *b;
int *xmin, *ymin, *xmax, *ymax;
{
int x, y;
int ixmin, ixmax;
int iymin, iymax;
short *sptr;
int xoffset;
int temp;
short excessmask;
sptr = b->base;
iymin = 100000;
iymax = -100000;
ixmin = 100000;
ixmax = -100000;
excessmask = 0xffff<<(15-((b->xsize-1)&0xf));
for(y=0; y<b->ysize; y++) {
xoffset = 0;
for(x=0; x<b->sper; x++) {
if(x == (b->sper-1))
*sptr &= excessmask;
if(*sptr) {
temp = xoffset + leftmost(*sptr);
if(temp<ixmin)
ixmin = temp;
temp = xoffset + rightmost(*sptr);
if(temp>ixmax)
ixmax = temp;
if(y<iymin)
iymin = y;
if(y>iymax)
iymax = y;
}
sptr++;
xoffset += 16;
}
}
if(iymin>iymax) {
*xmin = 0;
*xmax = 0;
*ymin = 0;
*ymax = 0;
return 0;
} else {
*xmin = ixmin;
*xmax = ixmax;
*ymin = iymin;
*ymax = iymax;
return 1;
}
}
static leftmost(val)
short val;
{
int i;
int bit;
bit = 0x8000;
for(i=0; i<16; i++) {
if(bit&val)
return i;
bit >>= 1;
}
return 0;
}
static rightmost(val)
short val;
{
int i;
int bit;
bit = 0x1;
for(i=16; i--;) {
if(bit&val)
return i;
bit <<= 1;
}
return 0;
}
int bmrasbytes(b)
Bitmap *b;
{
return b->ysize*2*b->sper;
}
Bitmap *bmread(fname)
char *fname;
{
FILE *inf;
Bitmap *b;
inf = gfxopen(fname,"r");
if(!inf) {
fprintf(stderr,"bmread: can't open input file [%s]\n",fname);
exit(1);
}
b = bmfromfile(inf);
fclose(inf);
return b;
}
Bitmap *bmfromfile(inf)
FILE *inf;
{
Bitmap *b;
long magic[2];
fread(magic,2*sizeof(long),1,inf);
if(magic[0] != BMMAGIC || magic[1] != BMMAGIC) {
fprintf(stderr,"bad magic number in bit map header\n");
return 0;
}
b = (Bitmap *)mymalloc(sizeof(Bitmap));
fread(&b->base,sizeof(short *),1,inf);
fread(&b->xsize,sizeof(short),1,inf);
fread(&b->ysize,sizeof(short),1,inf);
fread(&b->xorig,sizeof(short),1,inf);
fread(&b->yorig,sizeof(short),1,inf);
fread(&b->xmove,sizeof(short),1,inf);
fread(&b->ymove,sizeof(short),1,inf);
fread(&b->sper,sizeof(short),1,inf);
b->base = (short *)mymalloc(bmrasbytes(b));
fread(b->base,bmrasbytes(b),1,inf);
return b;
}
void bmtofile(outf,b)
FILE *outf;
Bitmap *b;
{
long magic[2];
magic[0] = BMMAGIC;
magic[1] = BMMAGIC;
fwrite(magic,2*sizeof(long),1,outf);
fwrite(&b->base,sizeof(short *),1,outf);
fwrite(&b->xsize,sizeof(short),1,outf);
fwrite(&b->ysize,sizeof(short),1,outf);
fwrite(&b->xorig,sizeof(short),1,outf);
fwrite(&b->yorig,sizeof(short),1,outf);
fwrite(&b->xmove,sizeof(short),1,outf);
fwrite(&b->ymove,sizeof(short),1,outf);
fwrite(&b->sper,sizeof(short),1,outf);
fwrite(b->base,bmrasbytes(b),1,outf);
}
void bmwrite(fname,b)
char *fname;
Bitmap *b;
{
FILE *outf;
outf = gfxopen(fname,"w");
if(!outf) {
fprintf(stderr,"bmwrite: can't open output file [%s]\n",fname);
exit(1);
}
bmtofile(outf,b);
fclose(outf);
}
void bmdrawbig(b,mag)
Bitmap *b;
int mag;
{
int x, y;
int bx, by;
int cdark, cbright;
by = 0;
cdark = grey(0.1);
cbright = grey(0.9);
for(y=0; y<b->ysize; y++) {
bx = 0;
for(x=0; x<b->xsize; x++) {
if(bmgetpix(b,x,y))
usecolor(cdark);
else
usecolor(cbright);
fillrecti(bx,by,bx+(mag-2),by+(mag-2));
if(x == b->xorig && y == b->yorig) {
rgb(1.0,0.0,0.0);
recti(bx,by,bx+(mag-2),by+(mag-2));
}
bx += mag;
}
by += mag;
}
}
void bmbigpix(b,x,y,mag)
Bitmap *b;
int x, y;
int mag;
{
int bx, by;
if(bmgetpix(b,x,y))
grey(0.1);
else
grey(0.9);
bx = x*mag;
by = y*mag;
fillrecti(bx,by,bx+(mag-2),by+(mag-2));
if(x == b->xorig && y == b->yorig) {
rgb(1.0,0.0,0.0);
recti(bx,by,bx+(mag-2),by+(mag-2));
}
}
void bmprint(bm)
Bitmap *bm;
{
printf("Bitmap size %d by %d\n",bm->xsize,bm->ysize);
printf("Bitmap orig %d by %d\n",bm->xorig,bm->yorig);
printf("Bitmap move %d by %d\n",bm->xmove,bm->ymove);
printf("Bitmap sper %d\n",bm->sper);
printf("Bitmap data %x\n",bm->base);
}